package com.jmxcfc.blfsc.common.common;

import com.jmxcfc.blfsc.common.common.enums.BaseErrorEnum;
import com.jmxcfc.blfsc.common.common.enums.ProcessStateEnum;
import com.jmxcfc.blfsc.common.common.request.BaseRequest;
import com.jmxcfc.blfsc.common.common.response.BaseResponse;
import com.jmxcfc.blfsc.common.exception.*;
import com.jmxcfc.blfsc.common.sms.BaseContext;
import com.jmxcfc.blfsc.common.validation.IRequestValidator;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;


/**
 *
 * 查询接口通用服务</br>
 * 这边捕获到的异常,处理状态:置为异常
 * T: BaseResponse响应体T
 * B: BaseRequest请求体B
 * E:BaseContext扩展体E
 */
public interface IQueryService<T, B, E> extends IResponseService<T,B>, IRequestValidator<B> {

    Logger log = LoggerFactory.getLogger(IQueryService.class);

    /**
     * 核心处理流程
     * @param request
     * @param baseContext
     * @return
     */
    default BaseResponse<T> execute(BaseRequest<B> request, BaseContext<E> baseContext) {
        //baseResponse这边注意空指针异常
        BaseResponse<T> baseResponse = new BaseResponse<>(BaseErrorEnum.START);
        try {
            initResponse(request, baseResponse);
            validHeader(request.getHeader(),baseContext);
            validBody(request.getBody(), baseContext);
            validBodyExtend(request.getBody(), baseContext);
            beforeOutbound(request, baseResponse, baseContext);
            outbound(request, baseResponse, baseContext);
            afterOutbound(request, baseResponse, baseContext);
        } catch (InitResponseException e) {
            log.error("请求流水号requestNo:{},初始化TransResponse异常,异常信息:{}", request.getHeader().getRequestNo(), e.getMessage());
            baseResponse.getHeader().setProcessState(ProcessStateEnum.EXCEPTION);
            baseResponse.getHeader().setResCode(InitResponseException.ERROR_CODE);
            baseResponse.getHeader().setResMessage(StringUtils.joinWith(ComConstants.AND, InitResponseException.ERROR_MSG, e.getMessage()));
        } catch (ValidHeaderException e) {
            log.error("请求流水号requestNo:{},验证header异常,异常信息:{}", request.getHeader().getRequestNo(), e.getMessage());
            baseResponse.getHeader().setProcessState(ProcessStateEnum.EXCEPTION);
            baseResponse.getHeader().setResCode(ValidHeaderException.ERROR_CODE);
            baseResponse.getHeader().setResMessage(ValidHeaderException.ERROR_MSG + e.getMessage());
        } catch (ValidBodyException e) {
            log.error("请求流水号requestNo:{},验证Body异常,异常信息:{}", request.getHeader().getRequestNo(), e.getMessage());
            baseResponse.getHeader().setProcessState(ProcessStateEnum.EXCEPTION);
            baseResponse.getHeader().setResCode(ValidBodyException.ERROR_CODE);
            baseResponse.getHeader().setResMessage(ValidBodyException.ERROR_MSG + e.getMessage());
        } catch (ValidBodyExtendException e) {
            log.error("请求流水号requestNo:{},验证Body扩展字段异常,异常信息:{}", request.getHeader().getRequestNo(), e.getMessage());
            baseResponse.getHeader().setProcessState(ProcessStateEnum.EXCEPTION);
            baseResponse.getHeader().setResCode(ValidBodyExtendException.ERROR_CODE);
            baseResponse.getHeader().setResMessage(ValidBodyExtendException.ERROR_MSG + e.getMessage());
        } catch (BeforeOutboundException e) {
            log.error("请求流水号requestNo:{},执行OutBound前异常,异常信息:{}", request.getHeader().getRequestNo(), e.getMessage());
            Throwable cause = e.getCause();
            if (cause instanceof RepetitionException) {
                baseResponse.getHeader().setProcessState(ProcessStateEnum.REPETITION);
                baseResponse.getHeader().setResCode(RepetitionException.ERROR_CODE);
                baseResponse.getHeader().setResMessage(StringUtils.joinWith(ComConstants.AND, BeforeOutboundException.ERROR_MSG, RepetitionException.ERROR_MSG));
            } else {
                baseResponse.getHeader().setProcessState(ProcessStateEnum.EXCEPTION);
                baseResponse.getHeader().setResCode(BeforeOutboundException.ERROR_CODE);
                baseResponse.getHeader().setResMessage(StringUtils.joinWith(ComConstants.AND, BeforeOutboundException.ERROR_MSG, e.getMessage()));
            }
        } catch (OutboundException e) {
            log.error("请求流水号requestNo:{},执行OutBound,异常信息:{}", request.getHeader().getRequestNo(), e.getMessage(), e);
            baseResponse.getHeader().setProcessState(ProcessStateEnum.EXCEPTION);
            baseResponse.getHeader().setResCode(OutboundException.ERROR_CODE);
            baseResponse.getHeader().setResMessage(StringUtils.joinWith(ComConstants.AND, OutboundException.ERROR_MSG, e.getMessage()));
        } catch (AfterOutboundException e) {
            log.error("请求流水号requestNo:{},执行OutBound后异常:{}", request.getHeader().getRequestNo(), e.getMessage(), e);
            //交互成功,只是内部处理失败
            baseResponse.getHeader().setProcessState(ProcessStateEnum.EXCEPTION);
            baseResponse.getHeader().setResCode(AfterOutboundException.ERROR_CODE);
            baseResponse.getHeader().setResMessage(StringUtils.joinWith(ComConstants.AND, AfterOutboundException.ERROR_MSG, e.getMessage()));
        } catch (Exception e) {
            log.error("请求流水号requestNo:{},执行主流程非常规异常:{}", request.getHeader().getRequestNo(), e.getMessage(), e);
            baseResponse.getHeader().setProcessState(ProcessStateEnum.EXCEPTION);
            baseResponse.getHeader().setResCode(BaseErrorEnum.EXCEPTION_UNEXPECTED.getValue());
            baseResponse.getHeader().setResMessage(StringUtils.joinWith(ComConstants.AND, BaseErrorEnum.EXCEPTION_UNEXPECTED.getMsg(), e.getMessage()));
        }
        baseResponse.getHeader().setResTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        return baseResponse;
    }

    /**
     * 调用外部之前执行
     * @param request
     * @param baseContext
     * @param response
     * @throws BeforeOutboundException
     */
    default void beforeOutbound(BaseRequest<B> request, BaseResponse<T> response, BaseContext<E> baseContext) throws BeforeOutboundException {
    }

    /**
     * 调用外部
     * 注意事项:
     * 实现方法内处理所有异常信息,否则抛出异常,则 processState 为 EXCEPTION
     *
     * @param request
     * @param response
     * @param baseContext
     * @throws OutboundException
     */
    void outbound(BaseRequest<B> request, BaseResponse<T> response, BaseContext<E> baseContext) throws OutboundException;

    /**
     * 调用外部之后执行
     * 注意事项:
     * 实现方法内处理所有异常信息,否则抛出异常,则 processState 为 EXCEPTION
     *
     * @param request
     * @param baseContext
     * @param response
     * @throws AfterOutboundException
     */
    default void afterOutbound(BaseRequest<B> request, BaseResponse<T> response, BaseContext<E> baseContext) throws AfterOutboundException {

    }
}